#include "SWAP.h"
#include <structure.h>
#include <OSProc.h>
#include <length.h>

#define DEFAULT_SIZE  512
#define DEFAULT_PER_SIZE  sizeof(_length)

#define PAGE_SIZE (1 << 12)


//#define _RECORD_SWAP(baseoffset,virtualoffset)  

namespace SWAP
{
  //  map<_length,_length> record;
  //  volatile Spareoffsetqueue* SWAPBasequeue = NULL;
  inline _length GetSpareOffset()
  {
    MUTEX_LOCK(&(SWAPBaseLock));
    if(SWAPBasequeue == NULL)
      {
	SWAPBasequeue = _Malloc(sizeof(Spareoffsetqueue));
	SWAPBasequeue->Spareoffsetqueue(DEFAULT_SIZE);
      }
    _length offset =  SWAPBasequeue->Pop();
    MUTEX_UNLOCK(&(SWAPBaseLock));
    return offset;
  }
  inline int PushSpareoffset(_length offset)
  {
    MUTEX_LOCK(&(SWAPBaseLock));
    if(SWAPBasequeue == NULL)
      {
	SWAPBasequeue = _Malloc(sizeof(Spareoffsetqueue));
	SWAPBasequeue->Spareoffsetqueue(DEFAULT_SIZE);
      }
    
    int ret =  SWAPBasequeue->Push(offset);
    MUTEX_UNLOCK(&(SWAPBaseLock));
    return ret;
  }

  inline int WriteToSWAP(_str swapout,_length offset)
  {
    _length baseoffset = GetSpareOffset();    
    RecordToMap(baseoffset,offset);
    ConvertToPrv(swapout,IFDSWAProot,Makelength<PAGE_SIZE>(),Makelength(baseoffset));
    
  }
  inline int ReadFromSWAP(_str swapin,_length offset)
  {
    _length baseoffset = GetRecord(offset);
    ConvertToPub(swapin,IFDSWAProot,Makelength<PAGE_SIZE>(),Makelength(baseoffset));
    PushSpareOffset(baseoffset);    
    UnrecordToMap(baseoffset,offset);
  }
  


}

template<typename T = _length>
class Spareoffsetqueue
  {
  public:
    Spareoffsetqueue(unsigned int num,const T& begin = 0);
    int Push(T offset);
    T Pop();
    int PushGroup(T* offset,_plong num);
    int PopGroup(T* offset,_ptlong num);
  private:
    queue Sparequeue;
    T Spareoffset;
  };
 
template<typename T> 
Spareoffsetqueue::Spareoffsetqueue(unsigned int num,const T& begin = 0)
{
  QueueInit(&Spareoffsetqueue,_Malloc(sizeof(T) * num),sizeof(T),num);
  Spareoffset = begin;
}

template<typename T>
T Spareoffsetqueue::Pop()
{
  
  if(QueueEmpty(&Spareoffsetqueue))
    return (Spareoffset++);
  else
    {
      T ret;
      QueuePop(&Spareoffsetqueue,&ret);
      return (ret);
    }
}
template<typename T>
inline int Spareoffsetqueue::Push(T offset)
{
  
  {
    QueuePush(&Spareoffsetqueue,&offset);
    
    return 1;
  }
  
}

